<template>
  <div class="files-page">
    <!-- 页面头部 -->
    <div class="page-header">
      <div class="header-left">
        <h1 class="page-title">文件管理</h1>
        <p class="page-description">
          管理系统中的上传文件，支持本地存储、MinIO和七牛云
        </p>
      </div>
      <div class="header-right">
        <el-button type="primary" @click="handleUpload">
          <Icon name="fa:upload" />
          上传文件
        </el-button>
      </div>
    </div>

    <!-- 统计信息 -->
    <el-row :gutter="24" class="stats-row">
      <el-col :xs="12" :sm="6">
        <el-card class="stat-card">
          <div class="stat-item">
            <div class="stat-icon" style="color: #409eff">
              <Icon name="fa:file" />
            </div>
            <div class="stat-content">
              <div class="stat-value">{{ stats.total_files || 0 }}</div>
              <div class="stat-label">总文件数</div>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :xs="12" :sm="6">
        <el-card class="stat-card">
          <div class="stat-item">
            <div class="stat-icon" style="color: #67c23a">
              <Icon name="fa:hdd-o" />
            </div>
            <div class="stat-content">
              <div class="stat-value">
                {{ formatFileSize(stats.total_size || 0) }}
              </div>
              <div class="stat-label">总存储大小</div>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :xs="12" :sm="6">
        <el-card class="stat-card">
          <div class="stat-item">
            <div class="stat-icon" style="color: #e6a23c">
              <Icon name="fa:folder" />
            </div>
            <div class="stat-content">
              <div class="stat-value">{{ stats.category_count || 0 }}</div>
              <div class="stat-label">分类数量</div>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :xs="12" :sm="6">
        <el-card class="stat-card">
          <div class="stat-item">
            <div class="stat-icon" style="color: #f56c6c">
              <Icon name="fa:cloud" />
            </div>
            <div class="stat-content">
              <div class="stat-value">{{ stats.local_files || 0 }}</div>
              <div class="stat-label">本地文件</div>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 搜索和筛选 -->
    <el-card class="filter-card">
      <el-form :model="filterForm" inline>
        <el-form-item label="文件分类">
          <el-select
            v-model="filterForm.category"
            placeholder="选择分类"
            clearable
          >
            <el-option label="项目文件" value="projects" />
            <el-option label="头像" value="avatars" />
            <el-option label="封面" value="covers" />
            <el-option label="文档" value="documents" />
            <el-option label="其他" value="others" />
          </el-select>
        </el-form-item>
        <el-form-item label="存储类型">
          <el-select
            v-model="filterForm.storageType"
            placeholder="选择存储类型"
            clearable
          >
            <el-option label="本地存储" value="local" />
            <el-option label="MinIO" value="minio" />
            <el-option label="七牛云" value="qiniu" />
          </el-select>
        </el-form-item>
        <el-form-item label="文件名">
          <el-input
            v-model="filterForm.fileName"
            placeholder="输入文件名"
            clearable
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button @click="handleReset">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 文件列表 -->
    <el-card>
      <template #header>
        <div class="table-header">
          <span>文件列表</span>
          <el-button type="text" @click="refreshList">
            <Icon name="fa:refresh" />
            刷新
          </el-button>
        </div>
      </template>

      <el-table :data="files" v-loading="loading" stripe>
        <el-table-column label="文件预览" width="120">
          <template #default="{ row }">
            <div class="file-preview">
              <div v-if="isImage(row.mime_type)" class="image-thumbnail">
                <el-image
                  :src="getFileUrl(row)"
                  :preview-src-list="[getFileUrl(row)]"
                  fit="cover"
                  class="thumbnail-image"
                  hide-on-click-modal
                >
                  <template #error>
                    <div class="image-error">
                      <Icon name="fa:image" class="error-icon" />
                    </div>
                  </template>
                </el-image>
              </div>
              <div v-else class="file-icon-container">
                <Icon
                  :name="getFileIcon(row.mime_type)"
                  class="file-icon-large"
                />
                <span class="file-extension">{{
                  getFileExtension(row.original_name)
                }}</span>
              </div>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="文件信息" min-width="250">
          <template #default="{ row }">
            <div class="file-info">
              <div class="file-name">
                <Icon :name="getFileIcon(row.mime_type)" class="file-icon" />
                <span class="file-name-text">{{ row.original_name }}</span>
              </div>
              <div class="file-meta">
                <span class="file-size">{{
                  formatFileSize(row.file_size)
                }}</span>
                <span class="file-type">{{ row.mime_type }}</span>
                <span class="file-date">{{ formatDate(row.created_at) }}</span>
              </div>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="category" label="分类" width="120">
          <template #default="{ row }">
            <el-tag :type="getCategoryTagType(row.category)" size="small">
              {{ getCategoryText(row.category) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="storage_type" label="存储类型" width="120">
          <template #default="{ row }">
            <el-tag :type="getStorageTagType(row.storage_type)" size="small">
              {{ getStorageTypeText(row.storage_type) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180" fixed="right">
          <template #default="{ row }">
            <div class="action-buttons">
              <el-button
                v-if="isImage(row.mime_type)"
                size="small"
                @click="handlePreview(row)"
                class="preview-btn"
              >
                <Icon name="fa:eye" />
                预览
              </el-button>
              <el-button
                size="small"
                type="primary"
                @click="handleDownload(row)"
                class="download-btn"
              >
                <Icon name="fa:download" />
                下载
              </el-button>
              <el-button
                size="small"
                type="danger"
                @click="handleDelete(row)"
                class="delete-btn"
              >
                <Icon name="fa:trash" />
                删除
              </el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="pagination">
        <el-pagination
          v-model:current-page="pagination.page"
          v-model:page-size="pagination.limit"
          :total="pagination.total"
          :page-sizes="[10, 20, 50, 100]"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handlePageChange"
        />
      </div>
    </el-card>

    <!-- 文件上传对话框 -->
    <el-dialog v-model="uploadDialogVisible" title="上传文件" width="500px">
      <el-upload
        ref="uploadRef"
        :auto-upload="false"
        :on-change="handleFileChange"
        :on-remove="handleFileRemove"
        :file-list="fileList"
        drag
        multiple
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <template #tip>
          <div class="el-upload__tip">
            支持图片、文档、压缩包等文件，单个文件不超过10MB
          </div>
        </template>
      </el-upload>

      <el-form :model="uploadForm" label-width="80px">
        <el-form-item label="文件分类">
          <el-select v-model="uploadForm.category" placeholder="选择分类">
            <el-option label="项目文件" value="projects" />
            <el-option label="头像" value="avatars" />
            <el-option label="封面" value="covers" />
            <el-option label="文档" value="documents" />
            <el-option label="其他" value="others" />
          </el-select>
        </el-form-item>
      </el-form>

      <template #footer>
        <el-button @click="uploadDialogVisible = false">取消</el-button>
        <el-button
          type="primary"
          :loading="uploading"
          @click="handleSubmitUpload"
        >
          上传
        </el-button>
      </template>
    </el-dialog>

    <!-- 图片预览对话框 -->
    <el-dialog
      v-model="previewDialogVisible"
      :title="previewFileName"
      :width="previewDialogWidth"
      :top="previewDialogTop"
      class="preview-dialog"
    >
      <div class="preview-container">
        <el-image
          :src="previewImageUrl"
          fit="contain"
          class="preview-image"
          :preview-src-list="[previewImageUrl]"
          @load="handleImageLoad"
        >
          <template #error>
            <div class="preview-error">
              <Icon name="fa:image" class="error-icon" />
              <p>图片加载失败</p>
            </div>
          </template>
        </el-image>
      </div>

      <template #footer>
        <el-button @click="previewDialogVisible = false">关闭</el-button>
        <el-button type="primary" @click="handleDownloadFromPreview"
          >下载</el-button
        >
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { UploadFilled } from "@element-plus/icons-vue";
import type { UploadFile, UploadFiles, UploadInstance } from "element-plus";

interface FileItem {
  id: number;
  original_name: string;
  file_name: string;
  file_path: string;
  file_size: number;
  mime_type: string;
  storage_type: "local" | "minio" | "qiniu";
  category: string;
  url?: string;
  full_path?: string;
  created_at: string;
  updated_at: string;
}

interface Stats {
  total_files: number;
  total_size: number;
  category_count: number;
  local_files: number;
  minio_files: number;
  qiniu_files: number;
}

// 响应式数据
const loading = ref(false);
const uploading = ref(false);
const uploadDialogVisible = ref(false);
const uploadRef = ref<UploadInstance>();
const fileList = ref<UploadFile[]>([]);
const previewDialogVisible = ref(false);
const previewImageUrl = ref("");
const previewFileName = ref("");
const previewDialogWidth = ref("80%");
const previewDialogTop = ref("5vh");
const imageNaturalSize = ref({ width: 0, height: 0 });

const files = ref<FileItem[]>([]);
const stats = ref<Stats>({
  total_files: 0,
  total_size: 0,
  category_count: 0,
  local_files: 0,
  minio_files: 0,
  qiniu_files: 0,
});

const filterForm = reactive({
  category: "",
  storageType: "",
  fileName: "",
});

const uploadForm = reactive({
  category: "projects",
});

const pagination = reactive({
  page: 1,
  limit: 20,
  total: 0,
});

// 方法

// 判断是否为图片
const isImage = (mimeType: string) => {
  return mimeType.startsWith("image/");
};

// 获取文件图标
const getFileIcon = (mimeType: string) => {
  if (mimeType.startsWith("image/")) return "fa:file-image-o";
  if (mimeType.startsWith("video/")) return "fa:file-video-o";
  if (mimeType.startsWith("audio/")) return "fa:file-audio-o";
  if (mimeType.includes("pdf")) return "fa:file-pdf-o";
  if (mimeType.includes("word")) return "fa:file-word-o";
  if (mimeType.includes("excel")) return "fa:file-excel-o";
  if (mimeType.includes("zip") || mimeType.includes("rar"))
    return "fa:file-archive-o";
  return "fa:file-o";
};

// 获取文件URL
const getFileUrl = (file: FileItem) => {
  return file.full_path || file.url || "";
};

// 获取文件扩展名
const getFileExtension = (fileName: string) => {
  const parts = fileName.split(".");
  return parts.length > 1 ? parts.pop()?.toUpperCase() : "FILE";
};

// 获取分类文本
const getCategoryText = (category: string) => {
  const texts: Record<string, string> = {
    projects: "项目文件",
    avatars: "头像",
    covers: "封面",
    documents: "文档",
    public: "公共文件",
    others: "其他",
  };
  return texts[category] || category;
};

// 获取分类标签类型
const getCategoryTagType = (category: string) => {
  const types: Record<string, any> = {
    projects: "primary",
    avatars: "success",
    covers: "warning",
    documents: "info",
    public: "danger",
    others: "",
  };
  return types[category] || "";
};

// 获取存储类型标签类型
const getStorageTagType = (storageType: string) => {
  const types: Record<string, any> = {
    local: "primary",
    minio: "success",
    qiniu: "warning",
  };
  return types[storageType] || "";
};

// 获取存储类型文本
const getStorageTypeText = (storageType: string) => {
  const texts: Record<string, string> = {
    local: "本地存储",
    minio: "MinIO",
    qiniu: "七牛云",
  };
  return texts[storageType] || storageType;
};

// 格式化文件大小
const formatFileSize = (bytes: number) => {
  if (bytes === 0) return "0 B";
  const k = 1024;
  const sizes = ["B", "KB", "MB", "GB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
};

// 格式化日期
const formatDate = (dateString: string) => {
  return new Date(dateString).toLocaleString("zh-CN");
};

// 加载文件列表
const loadFiles = async () => {
  loading.value = true;
  try {
    const params = new URLSearchParams();
    if (filterForm.category) params.append("category", filterForm.category);
    if (filterForm.storageType)
      params.append("storageType", filterForm.storageType);
    params.append("page", pagination.page.toString());
    params.append("limit", pagination.limit.toString());

    const response = await $fetch(`/api/files?${params}`);
    if (response.success && response.data) {
      files.value = response.data.files;
      pagination.total = response.data.pagination.total;
    }
  } catch (error: any) {
    console.error("加载文件列表失败:", error);
    ElMessage.error("加载文件列表失败");
  } finally {
    loading.value = false;
  }
};

// 加载统计信息
const loadStats = async () => {
  try {
    const response = await $fetch<{
      success: boolean;
      message: string;
      data: Stats;
    }>("/api/files/stats");
    if (response.success) {
      stats.value = response.data;
    } else {
      ElMessage.error(response.message);
    }
  } catch (error: any) {
    console.error("加载统计信息失败:", error);
  }
};

// 搜索
const handleSearch = () => {
  pagination.page = 1;
  loadFiles();
};

// 重置搜索
const handleReset = () => {
  filterForm.category = "";
  filterForm.storageType = "";
  filterForm.fileName = "";
  pagination.page = 1;
  loadFiles();
};

// 刷新列表
const refreshList = () => {
  loadFiles();
  loadStats();
};

// 分页大小改变
const handleSizeChange = (size: number) => {
  pagination.limit = size;
  pagination.page = 1;
  loadFiles();
};

// 页码改变
const handlePageChange = (page: number) => {
  pagination.page = page;
  loadFiles();
};

// 上传文件
const handleUpload = () => {
  uploadDialogVisible.value = true;
};

// 文件选择变化
const handleFileChange = (file: UploadFile, fileList: UploadFiles) => {
  // 可以在这里添加文件验证逻辑
};

// 文件移除
const handleFileRemove = (file: UploadFile, fileList: UploadFiles) => {
  // 处理文件移除
};

// 提交上传
const handleSubmitUpload = async () => {
  if (fileList.value.length === 0) {
    ElMessage.warning("请选择要上传的文件");
    return;
  }

  if (!uploadForm.category) {
    ElMessage.warning("请选择文件分类");
    return;
  }

  uploading.value = true;
  try {
    for (const file of fileList.value) {
      const formData = new FormData();
      formData.append("file", file.raw!);
      formData.append("category", uploadForm.category);

      const response = await $fetch<{ success: boolean; message: string }>(
        "/api/upload",
        {
          method: "POST",
          body: formData,
        }
      );

      if (!response.success) {
        throw new Error(response.message || "上传失败");
      }
    }

    ElMessage.success("文件上传成功");
    uploadDialogVisible.value = false;
    fileList.value = [];
    refreshList();
  } catch (error: any) {
    console.error("上传失败:", error);
    ElMessage.error(error.message || "上传失败");
  } finally {
    uploading.value = false;
  }
};

// 预览文件
const handlePreview = (file: FileItem) => {
  // 优先使用full_path，如果没有则使用url
  const previewUrl = file.full_path || file.url;
  if (previewUrl) {
    previewImageUrl.value = previewUrl;
    previewFileName.value = file.original_name;
    // 重置图片尺寸信息
    imageNaturalSize.value = { width: 0, height: 0 };
    // 设置默认弹窗尺寸
    previewDialogWidth.value = "80%";
    previewDialogTop.value = "5vh";
    previewDialogVisible.value = true;
  } else {
    ElMessage.warning("文件URL不存在");
  }
};

// 图片加载完成处理
const handleImageLoad = (event: Event) => {
  const img = event.target as HTMLImageElement;
  if (img) {
    imageNaturalSize.value = {
      width: img.naturalWidth,
      height: img.naturalHeight,
    };

    // 根据图片比例调整弹窗尺寸
    adjustPreviewDialogSize(img.naturalWidth, img.naturalHeight);
  }
};

// 根据图片比例调整弹窗尺寸
const adjustPreviewDialogSize = (width: number, height: number) => {
  if (width === 0 || height === 0) return;

  const aspectRatio = width / height;
  const screenWidth = window.innerWidth;
  const screenHeight = window.innerHeight;

  // 计算最大可用尺寸（留出边距）
  const maxWidth = screenWidth * 0.9;
  const maxHeight = screenHeight * 0.8;

  let dialogWidth = maxWidth;
  let dialogHeight = dialogWidth / aspectRatio;

  // 如果高度超过最大高度，则按高度限制
  if (dialogHeight > maxHeight) {
    dialogHeight = maxHeight;
    dialogWidth = dialogHeight * aspectRatio;
  }

  // 设置弹窗尺寸
  previewDialogWidth.value = `${Math.min(dialogWidth, maxWidth)}px`;

  // 计算顶部位置，使弹窗垂直居中
  const topPosition = (screenHeight - dialogHeight) / 2;
  previewDialogTop.value = `${Math.max(topPosition, 20)}px`;
};

// 下载文件
const handleDownload = async (file: FileItem) => {
  try {
    const fileUrl = file.full_path || file.url;
    if (!fileUrl) {
      ElMessage.warning("文件URL不存在");
      return;
    }

    // 创建下载链接
    const link = document.createElement("a");
    link.href = fileUrl;
    link.download = file.original_name;
    link.target = "_blank";
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    ElMessage.success("开始下载文件");
  } catch (error: any) {
    console.error("下载失败:", error);
    ElMessage.error("下载失败");
  }
};

// 从预览弹窗下载文件
const handleDownloadFromPreview = async () => {
  try {
    if (!previewImageUrl.value) {
      ElMessage.warning("文件URL不存在");
      return;
    }

    // 创建下载链接
    const link = document.createElement("a");
    link.href = previewImageUrl.value;
    link.download = previewFileName.value;
    link.target = "_blank";
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    ElMessage.success("开始下载文件");
  } catch (error: any) {
    console.error("下载失败:", error);
    ElMessage.error("下载失败");
  }
};

// 删除文件
const handleDelete = async (file: FileItem) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除文件 "${file.original_name}" 吗？此操作不可恢复。`,
      "确认删除",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }
    );

    const response = await $fetch(`/api/files/${file.id}`, {
      method: "DELETE",
    });

    if (response.success) {
      ElMessage.success("文件删除成功");
      refreshList();
    } else {
      throw new Error(response.message || "删除失败");
    }
  } catch (error: any) {
    if (error !== "cancel") {
      console.error("删除失败:", error);
      ElMessage.error(error.message || "删除失败");
    }
  }
};

// 生命周期
onMounted(() => {
  loadFiles();
  loadStats();
});
</script>

<style scoped>
.files-page {
  padding: 20px;
  background: #0f172a;
  min-height: 100vh;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
}

.page-title {
  font-size: 24px;
  font-weight: 600;
  margin: 0;
  background: linear-gradient(135deg, #f8fafc, #cbd5e1);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.page-description {
  color: #94a3b8;
  margin: 8px 0 0 0;
}

.stats-row {
  margin-bottom: 24px;
}

.stat-card {
  background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  transition: all 0.3s ease;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
    0 2px 4px -1px rgba(0, 0, 0, 0.06);
}

.stat-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
    0 4px 6px -2px rgba(0, 0, 0, 0.05);
  border-color: rgba(255, 255, 255, 0.2);
}

.stat-card .stat-item {
  display: flex;
  align-items: center;
}

.stat-card .stat-item .stat-icon {
  font-size: 36px;
  margin-right: 16px;
  opacity: 0.9;
}

.stat-card .stat-item .stat-value {
  font-size: 24px;
  font-weight: 600;
  color: #f8fafc;
}

.stat-card .stat-item .stat-label {
  color: #94a3b8;
  font-size: 14px;
}

.filter-card {
  margin-bottom: 24px;
  background: #1e293b;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
}

.table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.file-name {
  display: flex;
  align-items: center;
}

.file-name .file-icon {
  margin-right: 8px;
  color: #60a5fa;
}

.pagination {
  margin-top: 20px;
  text-align: center;
}

/* 文件预览样式 */
.file-preview {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 80px;
}

.image-thumbnail {
  width: 60px;
  height: 60px;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.thumbnail-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-error {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #1e293b;
  color: #64748b;
}

.error-icon {
  font-size: 24px;
}

.file-icon-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  background: #1e293b;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.file-icon-large {
  font-size: 24px;
  color: #60a5fa;
  margin-bottom: 4px;
}

.file-extension {
  font-size: 10px;
  color: #64748b;
  font-weight: 600;
}

/* 文件信息样式 */
.file-info {
  padding: 8px 0;
}

.file-name {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}

.file-name-text {
  font-weight: 500;
  color: #f8fafc;
  word-break: break-all;
}

.file-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 12px;
  color: #94a3b8;
}

.file-meta span {
  background: #1e293b;
  padding: 2px 6px;
  border-radius: 3px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

/* 操作按钮样式 */
.action-buttons {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.action-buttons .el-button {
  flex: 1;
  min-width: 50px;
  border-radius: 6px;
  transition: all 0.3s ease;
}

.preview-btn {
  background: linear-gradient(135deg, #22c55e, #16a34a);
  border-color: transparent;
  color: white;
}

.preview-btn:hover {
  background: linear-gradient(135deg, #16a34a, #15803d);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(34, 197, 94, 0.3);
}

.download-btn {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
  border-color: transparent;
  color: white;
}

.download-btn:hover {
  background: linear-gradient(135deg, #2563eb, #1d4ed8);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}

.delete-btn {
  background: linear-gradient(135deg, #ef4444, #dc2626);
  border-color: transparent;
  color: white;
}

.delete-btn:hover {
  background: linear-gradient(135deg, #dc2626, #b91c1c);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
}

/* 预览弹窗样式 */
.preview-dialog .el-dialog__body {
  padding: 0;
  background: #1e293b;
}

.preview-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 200px;
  max-height: 80vh;
  overflow: auto;
  padding: 20px;
  background: #1e293b;
}

.preview-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
  margin: 0 auto;
  border-radius: 8px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
}

.preview-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 200px;
  color: #94a3b8;
}

.preview-error .error-icon {
  font-size: 48px;
  margin-bottom: 16px;
}

/* Element Plus 组件暗色主题适配 */
:deep(.el-card) {
  background: #1e293b;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
}

:deep(.el-card__header) {
  background: #0f172a;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  color: #f8fafc;
  font-weight: 600;
}

:deep(.el-table) {
  background: #1e293b;
  color: #f8fafc;
}

:deep(.el-table th) {
  background: #0f172a !important;
  color: #f8fafc !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1) !important;
}

:deep(.el-table tr) {
  background: #1e293b !important;
}

:deep(.el-table--striped .el-table__body tr.el-table__row--striped td) {
  background: #334155 !important;
}

:deep(.el-table td) {
  border-bottom: 1px solid rgba(255, 255, 255, 0.1) !important;
  color: #f8fafc !important;
}

:deep(.el-table .cell) {
  color: #f8fafc !important;
}

:deep(.el-table .el-table__empty-block) {
  background: #1e293b !important;
}

:deep(.el-table .el-table__empty-text) {
  color: #94a3b8 !important;
}

:deep(.el-form-item__label) {
  color: #f8fafc !important;
}

:deep(.el-input__wrapper) {
  background: #0f172a !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  box-shadow: none !important;
}

:deep(.el-input__inner) {
  color: #f8fafc !important;
  background: transparent !important;
}

:deep(.el-input__inner::placeholder) {
  color: #64748b !important;
}

:deep(.el-select .el-input__wrapper) {
  background: #0f172a !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
}

:deep(.el-select-dropdown) {
  background: #1e293b !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
}

:deep(.el-select-dropdown__item) {
  color: #f8fafc !important;
}

:deep(.el-select-dropdown__item.hover) {
  background: #334155 !important;
}

:deep(.el-select-dropdown__item.selected) {
  background: #3b82f6 !important;
  color: white !important;
}

:deep(.el-pagination) {
  color: #f8fafc !important;
}

:deep(.el-pagination .btn-prev, .el-pagination .btn-next) {
  background: #0f172a !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  color: #f8fafc !important;
}

:deep(.el-pagination .number) {
  background: #0f172a !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  color: #f8fafc !important;
}

:deep(.el-pagination .number.active) {
  background: #3b82f6 !important;
  border-color: #3b82f6 !important;
  color: white !important;
}

:deep(.el-dialog) {
  background: #1e293b !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  border-radius: 12px !important;
}

:deep(.el-dialog__header) {
  background: #0f172a !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1) !important;
  color: #f8fafc !important;
}

:deep(.el-dialog__title) {
  color: #f8fafc !important;
}

:deep(.el-upload-dragger) {
  background: #0f172a !important;
  border: 2px dashed rgba(255, 255, 255, 0.1) !important;
  color: #f8fafc !important;
}

:deep(.el-upload-dragger:hover) {
  border-color: #3b82f6 !important;
}

:deep(.el-tag) {
  background: #334155 !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  color: #f8fafc !important;
}

:deep(.el-tag.el-tag--primary) {
  background: #1e40af !important;
  border-color: #3b82f6 !important;
}

:deep(.el-tag.el-tag--success) {
  background: #166534 !important;
  border-color: #22c55e !important;
}

:deep(.el-tag.el-tag--warning) {
  background: #92400e !important;
  border-color: #f59e0b !important;
}

:deep(.el-tag.el-tag--info) {
  background: #334155 !important;
  border-color: #64748b !important;
}

:deep(.el-tag.el-tag--danger) {
  background: #991b1b !important;
  border-color: #ef4444 !important;
}

/* 响应式调整 */
@media (max-width: 768px) {
  .action-buttons {
    flex-direction: column;
  }

  .file-meta {
    flex-direction: column;
    gap: 4px;
  }

  .preview-container {
    min-height: 300px;
    max-height: 60vh;
  }

  .page-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }

  .header-right {
    width: 100%;
  }

  .header-right .el-button {
    width: 100%;
  }
}
</style>
